/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package course.ya.doc.from.code.model.ast;

import course.ya.doc.from.code.model.lexer.project.NodeTree;
import course.ya.doc.from.code.model.statements.AStatement;
import course.ya.doc.from.code.model.statements.IStatementFactory;
import java.io.IOException;

/**
 *
 * @author dmitriy
 */
public class StatementTreeBuilder {

    private NodeTree syntaxTreeRoot;
    private IStatementFactory statementFactory;
    private StatementTree newTree;
    private String newTreeName;
    private int count = 1;

    private StatementTreeBuilder() {
    };

    /**
     *
     * @param syntaxTreeRoot
     * @param statementFactory
     * @param newTreeName
     */
    public StatementTreeBuilder(NodeTree syntaxTreeRoot, IStatementFactory statementFactory,
                                String newTreeName) {
        if (syntaxTreeRoot == null || statementFactory == null) {
            throw new IllegalArgumentException();
        }
        else {
            this.syntaxTreeRoot = syntaxTreeRoot;
            this.statementFactory = statementFactory;
            this.newTree = null;
            this.newTreeName = newTreeName;
        }
    }

    public StatementTree build() throws IOException {
        this.newTree = new StatementTree(newTreeName);
        privateBuilder(syntaxTreeRoot, null);
        return newTree;
    }

    private void privateBuilder(NodeTree syntaxTreeNode, StatementTreeNode parent) throws IOException {
        AStatement statement = statementFactory.getStatement(syntaxTreeNode.data);
        if (statement == null) {
            throw new IllegalArgumentException("StatementFactory returns null statement");
        }
        statement.setStatementId(count++);

        StatementTreeNode newNode = new StatementTreeNode(statement, parent);
        if (newTree.getRoot() == null) {
            newTree.setRoot(newNode);
        }
        else {
            parent.getChildren().add(newNode);
        }

        parent = newNode;
        for (NodeTree node : syntaxTreeNode.references) {
            privateBuilder(node, parent);
        }
    }
}
